//-----------------------------------------------------------------------
// <copyright file="DefaultPublicationSelectorPolicy.cs" company="iron9light">
//      Copyright (c) iron9light. All rights reserved.
// </copyright>
// <author>iron9light</author>
//-----------------------------------------------------------------------

namespace EventBrokerExtension
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Reflection;

    using Microsoft.Practices.ObjectBuilder2;

    /// <summary>
    /// An implementation of <see cref="IPublicationSelectorPolicy"/> that is aware of
    /// the build keys used by the unity container.
    /// </summary>
    public class DefaultPublicationSelectorPolicy : IPublicationSelectorPolicy
    {
        /// <summary>
        /// Return the sequence of publication informations.
        /// </summary>
        /// <param name="context">Current build context.</param>
        /// <returns>Sequence of publication informations.</returns>
        public IEnumerable<PublicationInfo> GetPublicationInfos(IBuilderContext context)
        {
            Type t = BuildKey.GetType(context.BuildKey);

            foreach (EventInfo eventInfo in t.GetEvents(BindingFlags.Public | BindingFlags.Instance))
            {
                if (eventInfo.GetAddMethod() != null && eventInfo.IsDefined(typeof(PublishesAttribute), true))
                {
                    foreach (PublicationInfo publicationInfo in GreatePublicatoinInfos(eventInfo))
                    {
                        yield return publicationInfo;
                    }
                }
            }
        }

        private static IEnumerable<PublicationInfo> GreatePublicatoinInfos(EventInfo eventInfo)
        {
            List<PublishesAttribute> attributes =
                    new List<PublishesAttribute>(
                            Sequence.OfType<PublishesAttribute>(
                                    eventInfo.GetCustomAttributes(typeof(PublishesAttribute), true)));

            Debug.Assert(attributes.Count == 1, "We must have one of these, otherwise this method would never have been called.");

            foreach (PublishesAttribute attribute in attributes)
            {
                yield return new PublicationInfo(attribute.EventTopic, eventInfo);
            }
        }
    }
}